﻿using System;
using System.Collections.Generic;
#if TASKSUPPORT
using System.Threading.Tasks;
using MugenMvvmToolkit.ViewModels;
using MugenMvvmToolkit.Annotations;
#endif
using System.Windows;
using JetBrains.Annotations;
using MugenMvvmToolkit.Infrastructure;
using MugenMvvmToolkit.Interfaces;
#if NETFX_CORE
using Windows.UI.Xaml;
#endif

namespace MugenMvvmToolkit.Utils
{
    /// <summary>
    ///     Represents the helper class.
    /// </summary>
    public static class MvvmUtils
    {
        #region Fields

#if TASKSUPPORT
        /// <summary>
        /// Gets the true task result.
        /// </summary>
        [SuppressTaskBusyHandler]
        public static readonly Task<bool> TrueTaskResult;

        /// <summary>
        /// Gets the false task result.
        /// </summary>
        [SuppressTaskBusyHandler]
        public static readonly Task<bool> FalseTaskResult;
#else
        /// <summary>
        /// Gets the true result.
        /// </summary>
        public static readonly IOperationResult<bool> TrueOperationResult;

        /// <summary>
        /// Gets the false result.
        /// </summary>
        public static readonly IOperationResult<bool> FalseOperationResult;
#endif

        #endregion

        #region Constructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="MvvmUtils" /> class.
        /// </summary>
        static MvvmUtils()
        {
#if TASKSUPPORT
            TrueTaskResult = MvvmExtensions.FromResult(true);
            FalseTaskResult = MvvmExtensions.FromResult(false);
#else
            TrueOperationResult = OperationResult.FromResult(true);
            FalseOperationResult = OperationResult.FromResult(false);
#endif
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the design bootstrapper.
        /// </summary>
        public static IBootstrapper DesignBootstrapper
        {
            get
            {
                if (!GlobalSettings.IsDesignMode)
                    Thrower.SupportedOnlyInDesignMode();
                IBootstrapper boot = null;
                if (Application.Current != null)
                    boot = Application.Current.Resources["DesignBootstrapper"] as IBootstrapper;
                if (boot == null)
                    Thrower.DesignBootstrapperNotFound();
// ReSharper disable once PossibleNullReferenceException
                if (!boot.IsStarted)
                    boot.Start();
                return boot;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        ///     Returns a weak-reference version of a delegate.
        /// </summary>
        /// <param name="originalAction">The delegate to convert to weak referencing.</param>
        /// <returns>A weak referencing delegate.</returns>
        public static T ConvertToWeakDelegate<T>([NotNull]T originalAction) where T : class
        {
            return ConvertToWeakDelegate(originalAction, null);
        }

        /// <summary>
        ///     Returns a weak-reference version of a delegate.
        /// </summary>
        /// <param name="originalAction">The delegate to convert to weak referencing.</param>
        /// <param name="unsubcribeDelegate">The unregister action to invoke if the target is garbage collected.</param>
        /// <returns>A weak referencing delegate.</returns>
        public static T ConvertToWeakDelegate<T>([NotNull]T originalAction, [CanBeNull] Action<T> unsubcribeDelegate) where T : class
        {
            var @delegate = originalAction as Delegate;
            if (@delegate == null)
                Thrower.ParameterTypeMismatch("originalAction", "delegate");
            Action<Delegate> uns = null;
            if (unsubcribeDelegate != null)
                uns = d => unsubcribeDelegate((T)((object)d));
            return (T)(object)MvvmUtilsInternal.ConvertToWeakDelegate(@delegate, uns);
        }

        /// <summary>
        ///     Finds the weak-delegate use a original delegate in the specified array of delegate.
        /// </summary>
        /// <param name="originalAction">The original delegate to find weak delegate.</param>
        /// <param name="delegates">The specified array of delegate</param>
        /// <returns>An instance of delegate.</returns>
        [CanBeNull]
        public static T FindWeakDelegateByOriginalDelegate<T>([NotNull]T originalAction, [NotNull] IList<Delegate> delegates)
            where T : class
        {
            var @delegate = originalAction as Delegate;
            if (@delegate == null)
                Thrower.ParameterTypeMismatch("originalAction", "delegate");
            return MvvmUtilsInternal.FindWeakDelegateByOriginalDelegate(@delegate, delegates) as T;
        }

        #endregion
    }
}